/**
 * <one line to give the program's name and a brief idea of what it does.>
 * Copyright (C) Aug 3, 2011  Isaias
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package redclient.client;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import redclient.Items.CustomField;
import redclient.Items.Issue;
import redclient.Items.Project;
import redclient.RedmineCredentials;

/**
 *
 * @author Isaias
 * @file RedRestParser.java
 */
public class RedRestParser {
    
    private static Pattern nonEstandardDateTimePattern;
    
    static{
        nonEstandardDateTimePattern = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d[+-]\\d\\d:\\d\\d");
    }

    public static synchronized List<Project> parseProjects(Document doc, RedmineCredentials credentials)
    {
        List<Project> projects = new Vector<Project>();
        try
        {
            NodeList xmlProjects = doc.getElementsByTagName("project");
            DateFormat formatter = new SimpleDateFormat(credentials.getDateFormat());
            for(int i = 0; i < xmlProjects.getLength(); i++)
            {
                Element xmlProject = (Element)xmlProjects.item(i);
                Project project = new Project();
                project.setProjectId(getElementValue(xmlProject, "id"));
                project.setName(getElementValue(xmlProject, "name"));
                project.setIdentifier(getElementValue(xmlProject, "identifier"));
                project.setDescription(getElementValue(xmlProject, "description"));
                project.setCreatedDate(formatter.parse(getDateTimeString(getElementValue(xmlProject, "created_on"))));
                project.setUpdatedDate(formatter.parse(getDateTimeString(getElementValue(xmlProject, "updated_on"))));
                project.setCredentials(credentials);
                projects.add(project);
            }
        }
        catch(Exception e)
        {
            e.printStackTrace(System.out);
        }
        return projects;
    }

    public static synchronized int parseIssues(Document doc, List<Issue> issues, String dateFormat)
    {
        int parsed = 0;
        try
        {
            NodeList xmlIssues = doc.getElementsByTagName("issue");
            DateFormat formatter1 = new SimpleDateFormat("yyyy-mm-dd");
            DateFormat formatter2 = new SimpleDateFormat(dateFormat);
            for(int i = 0; i < xmlIssues.getLength(); i++)
            {
                Element xmlIssue = (Element)xmlIssues.item(i);
                Issue issue = new Issue();
                issue.setId(getElementValue(xmlIssue, "id"));
                issue.setProjectId(getAttributeValue(xmlIssue, "id", "project"));
                issue.setTrakerId(Integer.parseInt(getAttributeValue(xmlIssue, "id", "tracker")));
                issue.setStatusId(Integer.parseInt(getAttributeValue(xmlIssue, "id", "status")));
                issue.setPriorityId(Integer.parseInt(getAttributeValue(xmlIssue, "id", "priority")));
                issue.setAuthorId(Integer.parseInt(getAttributeValue(xmlIssue, "id", "author")));
                issue.setAuthor(getAttributeValue(xmlIssue, "name", "author"));
                if( xmlIssue.getElementsByTagName("assigned_to").getLength() > 0 )
                {
                    issue.setAssignedToId(Integer.parseInt(getAttributeValue(xmlIssue, "id", "assigned_to")));
                    issue.setAssingedTo(getAttributeValue(xmlIssue, "name", "assigned_to"));
                }
                issue.setSubject(getElementValue(xmlIssue, "subject"));
                issue.setDescription( getElementValue(xmlIssue, "description"));
                issue.setStartDate(formatter1.parse(getElementValue(xmlIssue, "start_date")));
                String dueDate = getElementValue(xmlIssue, "due_date");
                issue.setDueDate(dueDate != null && dueDate.length() > 0 ? formatter1.parse(dueDate) : null);
                issue.setDoneRation(Integer.parseInt(getElementValue(xmlIssue, "done_ratio")));
                String stimatedTime = getElementValue(xmlIssue, "estimated_hours");
                Float vsT = stimatedTime != null && stimatedTime.length() > 0 ? Float.parseFloat(stimatedTime + "f") : 0;
                issue.setEstimatedHours(vsT);
                issue.setCreatedOn(formatter2.parse(getDateTimeString(getElementValue(xmlIssue, "created_on"))));
                issue.setUpdatedOn(formatter2.parse(getDateTimeString(getElementValue(xmlIssue, "updated_on"))));
                NodeList xmlCustomFields = xmlIssue.getElementsByTagName("custom_field");
                Element elci = null;
                List<CustomField> customFields = null;
                for(int ci = 0; ci < xmlCustomFields.getLength(); ci++)
                {
                    elci = (Element)xmlCustomFields.item(ci);
                    if( ci == 0 )
                    {
                        customFields = new ArrayList<CustomField>();
                    }
                    CustomField customField = new CustomField();
                    customField.setName(elci.getAttributes().getNamedItem("name").getNodeValue());
                    customField.setId(elci.getAttributes().getNamedItem("id").getNodeValue());
                    customField.setValue(elci.getTextContent());
                    customFields.add(customField);
                }
                issue.setCustomFileds(customFields);
                if( parsed == 0 && issues.contains(issue))
                {
                    break;
                }
                issues.add(issue);
                parsed++;
            }
        }
        catch(Exception e)
        {
            e.printStackTrace(System.out);
        }
        return parsed;
    }

    public static synchronized String getElementValue(Element node, String element)
    {
        return node.getElementsByTagName(element).item(0).getTextContent();
    }

    public static synchronized String getAttributeValue(Element node, String att, String element)
    {
        return node.getElementsByTagName(element).item(0).getAttributes().getNamedItem(att).getNodeValue();
    }
    
    private static synchronized String getDateTimeString(String dateTime)
    {
        Matcher matcher = nonEstandardDateTimePattern.matcher(dateTime);
        if( matcher.matches())
        {
            int pos = dateTime.lastIndexOf("-");
            dateTime = dateTime.substring(0, pos) + " GMT " + dateTime.substring(pos);
        }
        return dateTime;
    }
}
